home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Information / Digests / CSMP Digest / volume 1 / csmp-v1-205.txt (.txt) < prev    next >
Encoding:
LaTeX Document  |  1994-12-08  |  54.1 KB  |  1,233 lines  |  [TEXT/R*ch]

  1. C.S.M.P. Digest             Tue, 03 Nov 92       Volume 1 : Issue 205
  2. Today's Topics:
  3.     Think C Posix library
  4.     Wanted: Code fragment using FindFolder() to get prefs. folder
  5.     MacTCP, ASR's and completion routine hell
  6.     Getting a dialog in front
  7.     MACSBUG Dcmd for "Shut Down"
  8.     Best Debugger for MPW/C++?
  9.     Restart @interrupt time with VN
  10.     Parsing text files
  11. The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
  12. The digest is a collection of article threads from the internet newsgroup
  13. comp.sys.mac.programmer.  It is designed for people who read c.s.m.p. semi-
  14. regularly and want an archive of the discussions.  If you don't know what a
  15. newsgroup is, you probably don't have access to it.  Ask your systems
  16. administrator(s) for details.  (This means you can't post questions to the
  17. digest.)
  18. Each issue of the digest contains one or more sets of articles (called
  19. threads), with each set corresponding to a 'discussion' of a particular
  20. subject.  The articles are not edited; all articles included in this digest
  21. are in their original posted form (as received by our news server at
  22. cs.uoregon.edu).  Article threads are not added to the digest until the last
  23. article added to the thread is at least one month old (this is to ensure that
  24. the thread is dead before adding it to the digest).  Article threads that
  25. consist of only one message are generally not included in the digest.
  26. The entire digest is available for anonymous ftp from ftp.cs.uoregon.edu
  27. [128.223.8.8] in the directory /pub/mac/csmp-digest.  Be sure to read the
  28. file /pub/mac/csmp-digest/README before downloading any files.  The most
  29. recent issues are available from sumex-aim.stanford.edu [36.44.0.6] in the
  30. directory /info-mac/digest/csmp.  If you don't have ftp capability, the sumex
  31. archive has a mail server; send a message with the text '$MACarch help' (no
  32. quotes) to LISTSERV@ricevm1.rice.edu for more information.
  33. The digest is also available via email.  Just send a note saying that you
  34. want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
  35. automatically receive each new issue as it is created.  Sorry, back issues
  36. are not available through the mailing list.
  37. Send administrative mail to mkelly@cs.uoregon.edu.
  38. -------------------------------------------------------
  39. From: tim@maths.tcd.ie (Timothy Murphy)
  40. Subject: Think C Posix library
  41. Organization: Dept. of Maths, Trinity College, Dublin, Ireland.
  42. Date: Fri, 2 Oct 1992 17:09:08 GMT
  43. I recently ported a number of GNU programs to the Mac --
  44. including perl-4.035, rcs-5.6, diff-2.0 and patch-2.0.12u8 --
  45. using Think C.
  46. To avoid repetition, I wrote a library 
  47. called, rather grandiosely, ThinkCPosix or just Posix.
  48. (I say "wrote", but in fact code for many of the functions
  49. was collected from PD archives.)
  50. The following note describes what this library is,
  51. and how it can be obtained and used.
  52. ===================== ThinkCPosix.tex ===================== 
  53. \documentstyle[rcs,a4,12pt]{article}
  54. % rcs.sty is available from ftp.uni-stuttgart.de
  55. % in the directory soft/tex/latex-style-supported .
  56. \RCS$Revision: 1.1 $
  57. \RCS$Date: 1992/09/14 14:28:23 $
  58. \catcode`\"=\active
  59. \def"#1"{{\tt #1}}
  60. \begin{document}
  61. \title{A Posix Library for Think C}
  62. \author{Timothy Murphy\\
  63. Trinity College Dublin\\
  64. ("tim@maths.tcd.ie")}
  65. \date{\RCSDate\\[2mm]
  66. (Version \RCSRevision)}
  67. \maketitle
  68. \begin{abstract}
  69. This library is intended to supplement
  70. the ANSI and Unix libraries provided with Think C,
  71. by supplying as many of the missing Posix functions as possible.
  72. The library was developed to assist in porting
  73. GNU programs to the Macintosh\footnotemark.
  74. \end{abstract}
  75. \footnotetext{To date the author has ported
  76. the following GNU programs to the Mac:
  77. "diff-1.15",
  78. "patch-2.012u6",
  79. "rcs-5.6",
  80. "bison-1.18",
  81. "flex-2.3.7",
  82. "perl-4.035".}
  83. \section{Status}
  84. This library is placed in the Public Domain.
  85. It may be used and modified freely---%
  86. though the author would be grateful
  87. for notification of any such modifications,
  88. and would prefer if his name and e-mail address
  89. were left on all files, to this end.
  90. \section{Availability}
  91. The library is available by anonymous FTP from "ftp.maths.tcd.ie"
  92. in the directory "pub/Mac/ThinkCPosix-1.1".
  93. The compiled library is contained in the file "Posix.hqx".
  94. The source files are archived in "ThinkCPosix.hqx".
  95. This includes the Think C project "Posix.$\pi$".
  96. \section{Acknowledgements}
  97. The author has used freely code in the archives
  98. pointed out to him,
  99. in particular code by:
  100. Guido van Rossum ("guido@cwi.nl"), and
  101. Mathias Neearcher.
  102. (Where code is taken more or less verbatim,
  103. this is indicated in the relevant files.)
  104. He is also grateful for assistance from:
  105. Kenneth Seah ("kseah@procyon.austin.tx.us"),
  106. Sak Wathanasin ("sw@network-analysis-ltd.co.uk"),
  107. John W. Hardin ("hardin@mcc.com"), and
  108. Gary J. Henderson ("gary@iscnvx.lmsc.lockheed.com")
  109. \section{Posix}
  110. The use of the term ``Posix'' may be misleading---%
  111. it is certainly not meant to imply that the functions satisfy
  112. any Posix standards
  113. (of which the author is largely ignorant).
  114. It is intended simply as a description
  115. of the kind of functions included---%
  116. namely, those Posix functions not included
  117. in the Think C ANSI or Unix libraries.
  118. Many of the functions
  119. (in particular those in the file "dummy.c")
  120. do no more than return an appropriate value,
  121. indicating success or failure, as deemed appropriate.
  122. \section{Compilation}
  123. To re-compile the library,
  124. the included project "Posix.$\pi$" can be used.
  125. Just choose the "Build Library" option
  126. in the "Project" menu.
  127. The author has all the ANSI options turned on,
  128. as well as "Require prototypes".
  129. The 4-byte int option and 68020 code option
  130. are turned off.
  131. \section{Usage}
  132. Any file using the library should
  133. \begin{verbatim}
  134.       #include "ThinkCPosix.h"
  135. \end{verbatim}
  136. The header ("*.h") files should be placed somewhere
  137. in the Think C tree (ie below the Think C application).
  138. Whenever the "Posix" library is included,
  139. the Think C "MacTraps" library must also be included.
  140. (This could probably be avoided by abstracting
  141. the very few MacTraps functions called.
  142. But is that legal?)
  143. \section{Notes}
  144. These are a few random thoughts on some of the functions
  145. in the library.
  146. \begin{description}
  147. \item["alloca()"]
  148. This has been included to avoid duplication.
  149. Note that the prototype is "void *alloca(size\_t)",
  150. rather than "char *alloca(unsigned)".
  151. \item["dup()"]
  152. The functions "dup()" and "dup2()"
  153. (as implemented here)
  154. both close the original file after duplication.
  155. The reason for this is that Think C adopts the non-standard,
  156. if plausible, policy of including some file-functions
  157. (such as "close")
  158. as part of the file structure.
  159. So a "close(fd)" addressed to the original descriptor
  160. would also close the duplicate.
  161. (This may be a misunderstanding on the author's part.)
  162. \item["getpasswd()"]
  163. This (and one or two other functions)
  164. call "getlogin()" in the Think C Unix library
  165. to find the user's name.
  166. This latter must be set---%
  167. under System 7, at least---%
  168. in the "Sharing Setup" Control Panel,
  169. as described in the Macintosh Networking Reference manual.
  170. (I believe that under System 6 the username was changed
  171. on the Chooser panel.)
  172. \item["Open()"]
  173. The library includes a few ``substitute'' functions,
  174. eg "Perror()" and "Open()".
  175. The idea is that these can be used in place of
  176. "perror()" or "open()" by including the line
  177. \begin{verbatim}
  178.       #define open Open
  179. \end{verbatim}
  180. (or equivalent) at a judicious point in the program---%
  181. probably at the end of the configuration file,
  182. "conf.h" or whatever.
  183. The function "Open(char*, int, ...)"
  184. allows "open()" to take more than 2 arguments
  185. (as seems increasingly the practice),
  186. although these extra arguments are ignored.
  187. \item["Perror()"]
  188. This gives a brief description of the error (if it can)
  189. rather than just the number as in "perror()".
  190. The Think C function "strerror()"---%
  191. which the author had not noticed---%
  192. may render this unnecessary.
  193. \end{description}
  194. \section{Gnu ports}
  195. In principle the files 
  196. "patch.hqx", "diff.hqx", "perl.hqx", "ci.hqx", etc,
  197. in the directory "pub/Mac" at "ftp.maths.tcd.ie"
  198. contain the compiled applications.
  199. The source for these applications---%
  200. or rather, the diff-files from the standard distributions---%
  201. are in the appropriate subdirectory,
  202. eg "pub/Mac/diff-2.0".
  203. Unfortunately, none of these ports are yet documented properly.
  204. \section{Development}
  205. The author would be very grateful
  206. for any suggested improvements or extensions.
  207. Please send them to "tim@maths.tcd.ie".
  208. Any material used will be duly acknowledged.
  209. Implementation of functions related to 
  210. "pipe", "exec" and "spawn"
  211. would be particularly useful.
  212. (The "exec()" function in the Think C Unix library
  213. ignores all arguments except for the application to be launched.
  214. It would be nice if these arguments could be properly passed---%
  215. as must surely be feasible.)
  216. \end{document}
  217. ===========================================================
  218. - -- 
  219. Timothy Murphy  
  220. e-mail: tim@maths.tcd.ie
  221. tel: +353-1-2842366
  222. s-mail: School of Mathematics, Trinity College, Dublin 2, Ireland
  223. ---------------------------
  224. From: zimerman@phoenix.Princeton.EDU (Jacob Ben-david Zimmerman)
  225. Subject: Wanted: Code fragment using FindFolder() to get prefs. folder
  226. Organization: Princeton University
  227. Date: Thu, 1 Oct 1992 15:08:43 GMT
  228. Hi all. I'm sorry if this is a FAQ, but I'm having trouble figuring it
  229. out...I was wondering if anyone could provide me with a code fragment
  230. which illustrates how to use FindFolder() to get a VRefNum for the
  231. Preferences folder (and create on if it doesn't exist.)  I am using
  232. THink C 5.0.  In addition, I am more than a bit lost on exactly how to
  233. handle transferring a couple of hundred bytes to and from disk.  For
  234. example, IM talks about passing a buffer to the disk routines.  Is this
  235. a predefined buffer? Is it one I need to create myself?  Does it have to
  236. be of a certain size?  Any help is much appreciated! Thanks for your
  237. time and patience.
  238. - -JBZimmerman!
  239. 0.2 of a Mac programmer. :-) And working on it.
  240. - -- 
  241. ___________           |-Is that Scotch over there?  Hold everything.
  242.      ||               |                -Sean Connery, The Russia House
  243. ||   ||acob Zimmerman!+> <zimerman@phoenix.Princeton.EDU> INTERNET 
  244.  \===/                |  <zimerman@PUCC>                  BITNET
  245. +++++++++++++++++++++++++++
  246. From: oster@well.sf.ca.us (David Phillip Oster)
  247. Organization: Whole Earth 'Lectronic Link
  248. Date: Thu, 1 Oct 1992 16:20:22 GMT
  249. This is a fragment from one of my products.:
  250. OSErr InitialPreferencesLookUp(){
  251.     Str255    s;
  252.     LongInt    ff;
  253.     OSErr    val;
  254.     Integer prefVRef;
  255.     LongInt    prefDirId;
  256.     SFReply    reply;
  257. /* put the name of the preferences file in the reply record.
  258.     GetIndString(reply.fName, kMainStrs, kDefaultS);
  259.     if(noErr == Gestalt(gestaltFindFolderAttr, &ff) && (ff & (1L << gestaltFindFolderPresent))){
  260.         val = FindFolder(kOnSystemDisk, kPreferencesFolderType, kDontCreateFolder,
  261.             &prefVRef, &prefDirId);
  262.         if(noErr == val){ val = FSOpenWD(prefVRef, prefDirId, 'ERIC', &reply.vRefNum); }
  263.         if(noErr == val){ val = OpenIt(&reply); }
  264. /* do not close this working directory! */
  265.     }else{
  266. /* initialize the Str255 to "\p:Preferences:" note colons. */
  267.         GetIndString(s, kMainStrs, kPrefDirS);
  268.         Concat(s, reply.fName);        /* pin tail on name */
  269.         StrMove(s, reply.fName);    /* move result back to reply */
  270.         reply.vRefNum = world.sysVRefNum;
  271.         val = OpenIt(&reply);
  272.     return val;
  273. ---------------------------
  274. From: ejohnson@void.ncsa.uiuc.edu (Eric E. Johnson)
  275. Subject: MacTCP, ASR's and completion routine hell
  276. Organization: University of Illinois at Urbana
  277. Date: Thu, 1 Oct 1992 17:01:18 GMT
  278. I've been working on a networked, role playing game.  So those who can
  279. help will be helping to alleviate the relative dearth of games on the
  280. Macintosh.
  281. The game requires that there be frequent exchanges of data between the
  282. server and client.  The amount of data is small, under 100 bytes, and
  283. I've been referring to the exchanges as the heartbeat.  As an example,
  284. the heartbeat leaves the server, and is sent to the client.  The
  285. client reads it in, processes the client's data, and sends it back to
  286. the server.
  287. The idea is to have the rate of exchange as high as possible.  Since
  288. we are using a Unix based server, turn around time for the heartbeat
  289. on the server end is fairly fast.  Our problem has been the Mac end.
  290. After some initial work on the game, I realized that using null events
  291. from WaitNextEvent to parcel out time for networking wasn't working
  292. all that well.  Since there can be long delays between WaitNextEvents
  293. due to screen redraws, the networking can be very jittery.  The
  294. intelligent was to use interrupts, which would work during screen
  295. redraws.  
  296. MacTCP offers two types of notification routines.  One routine, the
  297. ASR, calls a function that you specify when new data has arrived, when
  298. the connection is closing, or other similar events.  The second
  299. notification routine is a routine that's called upon completion of an
  300. async routine.
  301. I tried writing the networking using ASR's alone, and another using
  302. async notification routines alone.  Neither worked very well.  The
  303. heartbeat would be exchanged for a while, but eventually a brutal
  304. crash would ensue.  Unfortunately, the crash was never consistent so
  305. it was difficult to debug.
  306. Last night, I decided to rewrite the client end on the Mac to use both
  307. an ASR and an async completion routine.  When the heartbeat arrives,
  308. MacTCP calls my ASR.  In my ASR, I issue an *async* read with a
  309. completion routine pointing to my send routine.  The ASR reads in the
  310. data, and exits fine.  When the async read is done, the completion
  311. routine is called, which then sends back out data.  The heartbeat in
  312. port is different from the heartbeat out port, which would eliminate
  313. any problems MacTCP would have with multiple async commands on the
  314. same port.
  315. This works, but comes to screaching halt on the sixteenth beat.  The
  316. server sends out the sixteenth beat, and nothing ever comes back from
  317. the client.  The client has consistently died on the 16th beat.  By
  318. crash, I mean the mouse no longer responds to movements, but oddly
  319. enough, I'm not tossed into MacsBug.
  320. Entering MacsBug via a hardware interrupt reveals very little.  'SC6'
  321. claims a6 points to a bad stack frame.  'SC7' has the same report
  322. every time, with the last five entries being the same every time.  One
  323. of the entries is labeled, _UnimplTrap.  UnimplementedTrap?  How bad
  324. is that?
  325. I've tried using MacsBug breakpoints to follow my interrupts, rather
  326. than using the Think C debugger.  This is where things get weird.  If
  327. I set an interrupt at my ASR, MacsBug will stop in the ASR when data
  328. arrives.  I always continue since the interrupt supposedly will run 15
  329. more times.  On the second return of the heartbeat from the server,
  330. MacsBug stops in the ASR.  However, when I tell MacsBug to continue
  331. with execution, MacsBug doesn't break into the ASR anymore.  However,
  332. the server does get the heartbeat back.
  333. Obvious problems...
  334.     Am I preserving A5?  The ASR's do that for you, and I've done
  335. so in my async completion code.
  336.     Turned off optimizations in Think C?  Yep.
  337.     Got Think C 5.0.3 for the Quadra?  Yep.
  338. Does MacsBug not deal to well with interrupts?  Has anyone had any
  339. luck with networking at interrupt level?  Has anyone tried to do
  340. anything similar to this?  Do completed async calls somehow linger
  341. around in MacTCP?  My thinking is that 16 beats is such a nice power
  342. of 2, and on the 16th beat, too many things are lingering around.
  343. Any suggestions?
  344. Eric Johnson
  345. +++++++++++++++++++++++++++
  346. From: oster@well.sf.ca.us (David Phillip Oster)
  347. Organization: Whole Earth 'Lectronic Link
  348. Date: Fri, 2 Oct 1992 07:34:13 GMT
  349. I have done this in a production system. My experience has been that networking
  350. is so slow, because of the potential of retransmits and time outs, that ANY
  351. useful network program must use asynch i/o and completion routines.
  352. tips:
  353. 1.) ignore the ASR(). it is very hard to get this to work right.
  354. 2.) ignore the MacTCP high level interfac e. It isn't async so it is a
  355. joke for anything real.
  356. 3.) Use a middle level interface that handles filling out the parameter
  357. block for you. This is pretty trivial to write.  Embed the parameter block
  358. as the first field of a larger structure, similar to the way a WindowPeek
  359. has a GrafPort embedded in the front of it, but most things just look at
  360. the struct on the front.
  361. 4.) in your main application, statically allocate all the data structures
  362. you'll need. Statically allocate an array of queue records (See OSUtils
  363. chap of Inside mac vol 2 for more information on these.)
  364. 5.) Use the global CurrentA5 to inititialize the ioCurrentA5 field of
  365. your extended parameter block.
  366. 6.) Your completion routine should save the value of A5 in a local,
  367. set A5 from  the ioCurrentA5 of the parameter block (passed in register A0
  368. I believe) and restore A5 on exit.  Look in the file <SetUpA4.h> for
  369. inspiration.
  370. 7.) Your completion routine can communicate with your event loop by 
  371. dequeuing queue records from the free list (See suggestion 4) and 
  372. enqueuing them on a pending list. Enqueu() and Dequeue() are guaranteed
  373. safe to call at interrupt time.
  374. 8.) If you need more help, contact me. My consulting rates are $85.00 per
  375. hour.
  376. +++++++++++++++++++++++++++
  377. From: resnick@cogsci.uiuc.edu (Pete Resnick)
  378. Organization: University of Illinois at Urbana
  379. Date: Fri, 2 Oct 1992 13:57:03 GMT
  380. Of MacTCP, oster@well.sf.ca.us (David Phillip Oster) writes:
  381. >1.) ignore the ASR(). it is very hard to get this to work right.
  382. Complaint: Anyone who ignores the ASR ignores ICMP messages. *Don't*
  383. ignore the ASR; report and act on ICMP destination unreachables. If
  384. you attempt a TCPActiveOpen and get an ICMP destination unreachable,
  385. TCPAbort the open and report to the user instead of doing what most
  386. programs do, which is wait up to a minute for the damn thing to time
  387. >7.) Your completion routine can communicate with your event loop by 
  388. >dequeuing queue records from the free list (See suggestion 4) and 
  389. >enqueuing them on a pending list. Enqueu() and Dequeue() are guaranteed
  390. >safe to call at interrupt time.
  391. I like this one; very slick way of doing it. Thanks David. However, it
  392. doesn't solve the reponse time problem that Eric was having, i.e.
  393. having to wait for the WNE to complete. Anyone have any slick
  394. strategies for that?
  395. - -- 
  396. Pete Resnick             (...so what is a mojo, and why would one be rising?)
  397. Graduate assistant - Philosophy Department, Gregory Hall, UIUC
  398. System manager - Cognitive Science Group, Beckman Institute, UIUC
  399. Internet: resnick@cogsci.uiuc.edu
  400. +++++++++++++++++++++++++++
  401. From: mandel@tmc.tulane.edu (Jeff E Mandel)
  402. Date: 2 Oct 92 15:16:35 GMT
  403. Organization: Tulane University School of Medicine
  404. In article <BvHyr4.J8D@news.cso.uiuc.edu> Pete Resnick,
  405. resnick@cogsci.uiuc.edu writes:
  406. >>7.) Your completion routine can communicate with your event loop by 
  407. >>dequeuing queue records from the free list (See suggestion 4) and 
  408. >>enqueuing them on a pending list. Enqueu() and Dequeue() are guaranteed
  409. >>safe to call at interrupt time.
  410. >I like this one; very slick way of doing it. Thanks David. However, it
  411. >doesn't solve the reponse time problem that Eric was having, i.e.
  412. >having to wait for the WNE to complete. Anyone have any slick
  413. >strategies for that?
  414. The "private event queue" approach is the best way I ever found to
  415. communicate between interrupt routines and "safe time". The advantage is
  416. that you can dequeue from your private event queue in a MenuHook or
  417. DragHook. It is also possible to break up your screen refresh into
  418. smaller segments and call the dequeue routine in the loop. Probably, you
  419. are drawing to a gWorld, then copying the gWorld to the screen; just
  420. divide the grafPort into an arbitray number of rects as wide as the
  421. screen, and copy each one of these to the screen, calling your dequeue
  422. routine each time. This will degrade screen performance a bit, but one
  423. way or another, you have to interleave your IO calls into the screen
  424. drawing, so doing it explicitly gives you more control over it. Besides,
  425. it will give your game that vertical wipe effect so popular in video
  426. arcade games :-).
  427. There is another way to do what Eric wants, as he really only needs to be
  428. able to queue another IO call, and can preallocate enough parameter
  429. blocks to suffice. The solution I employed in a different problem (but
  430. conceptually similar) was to have a very short completion routine which
  431. queued a deferred task, which did the processing. The deferred task fires
  432. "soon", but there is no guarantee that it will fire before the next
  433. interrupt, or not be interrupted itself, so you need some sort of guard
  434. structures; a spin lock or a semaphore or such, so you don't get confused
  435. about what has and hasn't been done. Why go to the trouble? The deferred
  436. task doesn't block other interrupts, so the mouse doesn't get that jumpy
  437. look (which you can tolerate while initializing a disk, but would drive
  438. your game players crazy).
  439. Hope this helps,
  440. Jeff E Mandel MD MS
  441. Associate Professor of Anesthesiology
  442. Tulane University School of Medicine
  443. New Orleans, LA
  444. mandel@vax.anes.tulane.edu
  445. ---------------------------
  446. From: karlberg@e.kth.se (KRILLE_KROKODIL)
  447. Subject: Getting a dialog in front
  448. Date: 1 Oct 92 23:32:07 GMT
  449. Organization: KTH, Royal Institute of Technology, School of Electrical Engineering
  450. When I start a program I've written in Think Pascal it's supposed to
  451. show a dialog before it enters the main loop. The wierd thing is that 
  452. although I pass behind=POINTER(-1) when I call GetNewDialog it gets 
  453. drawn behind all the other windows on the screen, as does the main 
  454. window until I enter the main loop. Why is that and how do I get round
  455. Martin
  456. - -------------------------------------------------------------------------------
  457.                                     If you have a living frog for breakfast,   
  458.                                     nothing worse can happen during the day.  
  459. +++++++++++++++++++++++++++
  460. From: absurd@applelink.apple.com (Tim Dierks, software saboteur)
  461. Date: 2 Oct 92 18:56:03 GMT
  462. Organization: MacDTS Marauders
  463. In article <00961772.8D5273A0@e.kth.se>, karlberg@e.kth.se
  464. (KRILLE_KROKODIL) wrote:
  465. > When I start a program I've written in Think Pascal it's supposed to
  466. > show a dialog before it enters the main loop. The wierd thing is that 
  467. > although I pass behind=POINTER(-1) when I call GetNewDialog it gets 
  468. > drawn behind all the other windows on the screen, as does the main 
  469. > window until I enter the main loop. Why is that and how do I get round
  470. > it?
  471. > Martin
  472. MultiFinder, and System 7, for resons unknown to me, don't bring an
  473. application to the foreground until its event loop starts up; you
  474. can force it to bring you forward by making a few event calls; the
  475. canonical sequence is to call EventAvail() three times; you'll
  476. then be brought to the front.
  477. Tim Dierks
  478. MacDTS, but I squeak with glee
  479. ---------------------------
  480. From: Joel Sumner <js17@cornell.edu>
  481. Subject: MACSBUG Dcmd for "Shut Down"
  482. Organization: Trapped at Cornell University
  483. Date: Mon, 28 Sep 1992 20:19:54 GMT
  484. Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug?  I have
  485. powerbook 100 and the ONLY way to shut off the power is from the Finder 
  486. ShutDown command (there is this thing about not having a power switch or
  487. a power cord to unplug that causes problems... <grin>).  Occasionally,
  488. when I crash the thing, I  don't want to wait for it to do a full re-boot
  489. just to select "Shut Down".  Has anyone written a Macs Bug DCMD (or any
  490. other method from MacsBug) which will do the same thing?  Not even a full
  491. OS shutdown, just a "Power Off" would be nice....
  492. - -Joel
  493. Joel Sumner
  494. js17@cornell.edu
  495. q4kx@cornella (Bitnet)
  496. - -----------------------------------------------------------
  497. .sig under construction (like the rest of Cornell)
  498. +++++++++++++++++++++++++++
  499. From: howes@cat15.cs.wisc.edu (Glenn Howes)
  500. Date: 28 Sep 92 22:22:20 GMT
  501. Organization: University of Wisconsin, Madison -- Computer Sciences Dept.
  502. In article <1992Sep28.201954.20830@mail.cornell.edu> Joel Sumner <js17@cornell.edu> writes:
  503. >Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug?  I have
  504. >powerbook 100 and the ONLY way to shut off the power is from the Finder 
  505. >ShutDown command (there is this thing about not having a power switch or
  506. >a power cord to unplug that causes problems... <grin>).  Occasionally,
  507. >when I crash the thing, I  don't want to wait for it to do a full re-boot
  508. >just to select "Shut Down".  Has anyone written a Macs Bug DCMD (or any
  509. >other method from MacsBug) which will do the same thing?  Not even a full
  510. >OS shutdown, just a "Power Off" would be nice....
  511. It appears to me that pressing both the interupt and the reset buttons and
  512. holding them simultaneously causes a shutdown. Can anybody confirm that
  513. this will also cause the heads to park?
  514. - -- 
  515. - ------------------------------------------------------------------
  516. Glenn R. Howes              Internet: howes@bert.chem.wisc.edu
  517. author: Kermit Tool GH      // Picard & Riker in '92 
  518. - ------------------------------------------------------------------
  519. +++++++++++++++++++++++++++
  520. From: crod@cc.curtin.edu.au (Scott Kevill)
  521. Organization: Curtin University of Technology
  522. Date: Fri, 2 Oct 1992 01:40:06 GMT
  523. Hi Joel,
  524. If you didn't have a DCMD, you could always use the trap call
  525. (like the ExitToShell used in the old days of ROM mini-debuggers)
  526. as I do.
  527. At the debugger prompt, type :
  528. SM 0 3F3C 0 1 A895
  529. or with MacsBug, you can do this in one line :
  530. SM 0 3F3C 0 1 A895;G 0
  531. After using this plenty of times for a quick shutdown, especially
  532. on floppy systems, it is fairly quick to type and has the advantage
  533. of working on any debugger.
  534. Hope this helps !
  535. Scott
  536. +-----------------------+--------------------------------------+
  537. I Scott Kevill          I   "Be like me, be original"          I
  538. I crod@cc.curtin.edu.au I                              -- Me   I
  539. +-----------------------+--------------------------------------+
  540. In article <1992Sep28.201954.20830@mail.cornell.edu>, js17@cornell.edu (Joel Sumner) writes:
  541. > Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug?  I have
  542. > powerbook 100 and the ONLY way to shut off the power is from the Finder 
  543. > ShutDown command (there is this thing about not having a power switch or
  544. > a power cord to unplug that causes problems... <grin>).  Occasionally,
  545. > when I crash the thing, I  don't want to wait for it to do a full re-boot
  546. > just to select "Shut Down".  Has anyone written a Macs Bug DCMD (or any
  547. > other method from MacsBug) which will do the same thing?  Not even a full
  548. > OS shutdown, just a "Power Off" would be nice....
  549. > -Joel
  550. > Joel Sumner
  551. > js17@cornell.edu
  552. > q4kx@cornella (Bitnet)
  553. > -----------------------------------------------------------
  554. > .sig under construction (like the rest of Cornell)
  555. +++++++++++++++++++++++++++
  556. From: rjc@monet.ccs.itd.umich.edu (Robert John Churchill)
  557. Organization: University of Michigan
  558. Date: Fri, 2 Oct 1992 13:17:02 GMT
  559. In article <1992Oct2.104006.1@cc.curtin.edu.au>, crod@cc.curtin.edu.au
  560. (Scott Kevill) wrote:
  561. > If you didn't have a DCMD, you could always use the trap call
  562. > (like the ExitToShell used in the old days of ROM mini-debuggers)
  563. > as I do.
  564. > In article <1992Sep28.201954.20830@mail.cornell.edu>, js17@cornell.edu (Joel Sumner) writes:
  565. > > Has anyone written a "Shut Down" or "Power Off" DCMD for MacsBug?
  566. Go into Macsbug and type  "G Power"   :)
  567. ---------------------------
  568. From: D_Gladstone@cs.aukuni.ac.nz (David Gladstone)
  569. Subject: Best Debugger for MPW/C++?
  570. Date: 28 Sep 92 23:39:06 GMT
  571. Organization: Computer Science Dept., Auckland University.
  572. I am soon to be embarking on a project that will require the use of C++.
  573. Currently we have MPW C++ v3.1 and Zortech C++ v2.1 for MPW.  The question
  574. I have is about debuggers.  From what I've read in the August APDA
  575. catalogue, there are two options:
  576. SADE 1.3.2 : Good scripting, but does not appear to have support for class
  577.              browsing etc.
  578. SOURCEBUG v1.0.1 : "Special support for debugging MacApp and object
  579.                    oriented code."
  580.                    "A browser interface to display the classes and methods
  581.                       of MacApp or an object oriented program."
  582. How do these products fare?  Is the class browser in SourceBug better,
  583. worse, or on par with Think Pascal's (with which I am familiar)?
  584. Are there any alternative products on the market which are better?
  585. If SADE and SOURCEBUG are the only viable products, which should I buy?
  586. should I buy both?
  587. Either post or email your recommendations.
  588. Thank you.
  589. D_Gladstone@cs.aukuni.ac.nz   // Dept of Computer Science, // In real life
  590. =============================// University of Auckland,   // as opposed to
  591. Ph: (64) (9) 373-7599 x5336 // Private Bag 92019,        // in a computer:
  592. Fax:(64) (9) 373-7453      // Auckland, New Zealand.    // David Gladstone
  593. +++++++++++++++++++++++++++
  594. From: Bruce.Hoult@bbs.actrix.gen.nz
  595. Date: Fri, 2 Oct 1992 02:28:49 GMT
  596. Organization: Actrix Information Exchange
  597. In article <1992Sep28.233906.26728@cs.aukuni.ac.nz> David Gladstone <D_Gladstone@cs.aukuni.ac.nz> writes:
  598. > I am soon to be embarking on a project that will require the use of C++.
  599. > Currently we have MPW C++ v3.1 and Zortech C++ v2.1 for MPW.  The question
  600. > I have is about debuggers.  From what I've read in the August APDA
  601. > catalogue, there are two options:
  602. > SADE 1.3.2 : Good scripting, but does not appear to have support for class
  603. >              browsing etc.
  604. > SOURCEBUG v1.0.1 : "Special support for debugging MacApp and object
  605. >                    oriented code."
  606. >                    "A browser interface to display the classes and methods
  607. >                       of MacApp or an object oriented program."
  608. I use both daily.  I wouldn't want to be without either, although if I
  609. had to choose only one I think, uuuuuuhhhh, when you need SADE you
  610. *need* it.
  611. SourceBug is better for general noodling around.  It's marginally
  612. better for tracing control-flow type problems.  It's much better than
  613. SADE for checking the match between source code and machine code -- you
  614. can display two windows of the same function, one in source the other
  615. in ASM and you can set breakpoints or singlestep in either view at
  616. will.  You can have continuously updated windows containing the values
  617. in registers *and* in high-level program variables at the same time.
  618. It's easier to drop down into MACSBUG and come back again than in SADE
  619. (actually I 've never figured out how to do that in SADE...).
  620. SourceBug is immeasurably better than SADE at tracing around the data
  621. of PascalObjects -- you can click on the name of a class and a list of
  622. all currently instantiated objects of that class appears.  Clicking on
  623. an object shows the fields of that object.
  624. Like MPW itself, SADE is programmable.  That means SADE vs SourceBug
  625. is a bit like MPW vs THINK.  SADE has less built in than SourceBug,
  626. but you can probably add everything I listed in the previous paragraph
  627. to it if you take the time to write the necesary scripts.  I use SADE
  628. less than SourceBug, but when I do use it it's for its repeatability,
  629. its non-object data examining ability or its memory-stomper catching.
  630. Ever have a bug that only shows up after you go through two dozen
  631. steps, then crashes the Mac?  Get sick of manually steering your
  632. program through those steps time after time?  With SADE you can write
  633. a little script that starts your program and runs it to a breakpoint,
  634. changes the values of a couple of variables or sets the PC to a
  635. different line (to simulate the effects of getting an event from the
  636. user, or otherwise guide the program), runs to another breakpoint etc
  637. etc until you get to the problem situation.  OK, that takes a while to
  638. set up (especially with a certain misfeature added in SADE 1.3 (?)
  639. that makes you chain actions wiht onEntry actions instead of using a
  640. straight line script), but sometimes the alternatives are worse.
  641. SADE is also good for examining data that the .SYM file doesn't
  642. properly describe.  My main example of that is a pseudo-template type
  643. (done using macros) I use extensively that stores a dynamic array of
  644. xxxx's in a handle.  SourceBug just shows the whole array as a handle,
  645. but SADE can be convinced to show it as an array of xxxx's.
  646. The latest SADE (but you need ETO to get it) has the ability to use the MMU
  647. to protect areas of memory to catch memory stomping bugs.  This can save
  648. lots of aggro sometimes.
  649. If you've got MPW and  C++ (and therefore C) and are getting SADE and
  650. SourceBug you should probably consider getting the full ETO package instead.
  651. It's a tad expensive but it's pretty good.
  652. - -- Bruce
  653. - -- 
  654. Bruce.Hoult@bbs.actrix.gen.nz   Twisted pair: +64 4 477 2116
  655. BIX: brucehoult                 Last Resort:  PO Box 4145 Wellington, NZ
  656. "Cray's producing a 500 MIPS personal computer with 256MB RAM and 8 GB
  657. hard disk that fits in your pocket!"   "Great!  Is it PC compatible?"
  658. ---------------------------
  659. From: stud08@cc4.kuleuven.ac.be (Karl Pottie)
  660. Subject: Restart @interrupt time with VN
  661. Date: 28 Sep 92 12:52:19 GMT
  662. Organization: K.U.Leuven - Academic Computing Center
  663. I'm writing an init which reboots the mac after a system error. For this
  664. purpose, I call the toolbox routine Restart() at interrupt time. This
  665. works fine except when VM is running. When VM is running the mac simply
  666. blanks its screen and locks up. I tried using DeferUserFN(), but it didn't
  667. help.
  668. How do I reboot (restart) a macintosh at interrupt time ? Any quick
  669. and dirty methods ? Any clean method ?
  670. Please respond to me directly
  671. +++++++++++++++++++++++++++
  672. From: jpugh@apple.com (Jon Pugh)
  673. Date: 30 Sep 92 03:38:17 GMT
  674. Organization: Apple Computer, Inc.
  675. In article <1992Sep28.125124@cc4.kuleuven.ac.be>, stud08@cc4.kuleuven.ac.be
  676. (Karl Pottie) wrote:
  677. > Hi,
  678. > I'm writing an init which reboots the mac after a system error. For this
  679. > purpose, I call the toolbox routine Restart() at interrupt time. This
  680. > works fine except when VM is running. When VM is running the mac simply
  681. > blanks its screen and locks up. I tried using DeferUserFN(), but it didn't
  682. > help.
  683. > How do I reboot (restart) a macintosh at interrupt time ? Any quick
  684. > and dirty methods ? Any clean method ?
  685. We spent a good half an hour laughing about this one in DTS today.  It even
  686. got posted to the unofficial "Wall of Shame".
  687. I think Baumwell's suggestion was best.  Stuff the MrBusError number into
  688. the bus error exception vector, then execute that same bus error number. 
  689. That way you get a double exception and the machine reboots.
  690. ---------------------------
  691. From: u2005681@ucsvc.ucs.unimelb.edu.au
  692. Subject: Parsing text files
  693. Date: 30 Sep 92 04:03:35 GMT
  694. Organization: The University of Melbourne
  695. Hi folks,
  696. I wonder if any of you people out there can give me some advice?
  697. I've been programming for quite a while but I havn't had much to do
  698. with the Mac file system and related toolbox calls.
  699. As part of a new application, I am trying to read a text file of numbers
  700. and strings into a series of variables. The idea is to use the numbers as
  701. co-efficients for a simulation and the strings as labels for various graphs.
  702. As I understand it, the Mac OS deals with text files as UNIX-C does with
  703. binary files ie you specify how many bytes to read and what buffer to read
  704. them into. But in the absence of a standard library, how is it possible to 
  705. read numbers and strings of differing lengths?
  706. An explanation (or even some source code in C) would be most excellent.
  707. I appreciate your time and effort.
  708. C.Hofflin
  709. - ----------------------------------------------
  710. "Insert your own clever, deep and meaningful quote here"
  711. +++++++++++++++++++++++++++
  712. From: kdlee@milli.cs.umn.edu (Kevin D. Lee)
  713. Organization: University of Minnesota, Minneapolis, CSci dept.
  714. Date: Wed, 30 Sep 1992 14:46:24 GMT
  715. In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au> u2005681@ucsvc.ucs.unimelb.edu.au writes:
  716. >Hi folks,
  717. >I wonder if any of you people out there can give me some advice?
  718. >I've been programming for quite a while but I havn't had much to do
  719. >with the Mac file system and related toolbox calls.
  720. >As part of a new application, I am trying to read a text file of numbers
  721. >and strings into a series of variables. The idea is to use the numbers as
  722. >co-efficients for a simulation and the strings as labels for various graphs.
  723. >As I understand it, the Mac OS deals with text files as UNIX-C does with
  724. >binary files ie you specify how many bytes to read and what buffer to read
  725. >them into. But in the absence of a standard library, how is it possible to 
  726. >read numbers and strings of differing lengths?
  727. >An explanation (or even some source code in C) would be most excellent.
  728. >I appreciate your time and effort.
  729. >C.Hofflin
  730. >----------------------------------------------
  731. >"Insert your own clever, deep and meaningful quote here"
  732. I handle parsing a text file by reading all of the data into a handle.
  733. My next step is to lock the handle and start to dereference it by assigning
  734. a char pointer to point to the first byte. I then use the sscanf function 
  735. from ansi c to parse out the items that I am interested in.  After each
  736. sscanf make sure you move your char pointer to the correct position.  If
  737. this is to vague let me know and I will provide more details.
  738. Kevin Lee
  739. +++++++++++++++++++++++++++
  740. From: bpb9204@tamsun.tamu.edu (Brent)
  741. Organization: Texas A&M Univ., Inc.
  742. Date: Wed, 30 Sep 1992 14:50:12 GMT
  743. u2005681@ucsvc.ucs.unimelb.edu.au writes:
  744. |As part of a new application, I am trying to read a text file of numbers
  745. |and strings into a series of variables. The idea is to use the numbers as
  746. |co-efficients for a simulation and the strings as labels for various graphs.
  747. |As I understand it, the Mac OS deals with text files as UNIX-C does with
  748. |binary files ie you specify how many bytes to read and what buffer to read
  749. |them into. But in the absence of a standard library, how is it possible to 
  750. |read numbers and strings of differing lengths?
  751. What do you mean, "absence of a standard library?"  What are you using?
  752. |An explanation (or even some source code in C) would be most excellent.
  753. I don't know the format of what you want to read in, so you'll have to
  754. massage the following into your own form.
  755. The idea is to use your own buffering.  You do this by either using an
  756. array or allocating (with NewPtr() or NewHandle() ) an appropriately-sized
  757. buffer.  The size of the buffer is important - if you make it a multiple
  758. of the disk block size, your reads will be much faster.  A good buffer
  759. size is 1024 or 2048 bytes.  (Is a mac disk block 512 bytes? or 1024?)
  760. What you'll do is pass bits of your buffer to string conversion utilities
  761. like Str2Num.  This will convert the string representation of a number
  762. into an Extended type.  When you are reading a string, just copy characters
  763. from the buffer to your string array directly.  
  764.   Note: Str2Num takes a "DecStr" type, which is effectively an array
  765.   of 255 characters.  That's how long your number representation can be.  
  766. When your buffer position is equal to the length of the buffer, it's time
  767. to read in another block of data.
  768. This idea isn't difficult to implement and can be easily done in an
  769. afternoon, for sure.  Some C books mention buffering, if you need a reference.
  770. I decided to go ahead and write some simple stuff.  Here is my 10 minute
  771. hack:
  772. - -------  pseudo-C follows
  773. char buffer[1024];
  774. int bufpos;
  775. int endoffile=0;
  776. LoadBuffer()
  777.    OSErr err;
  778.    long count = 1024;
  779. /* inputRefNum is reference number of a pre-opened input file **/
  780.    err = FSRead( inputRefNum, &count, buffer);  /* check error result */
  781.    if (count == 0)
  782.      endoffile = 1;
  783.    bufpos = 0;
  784. ScanNumber(Extended *e, )
  785.    *e = Str2Num( &buffer[bufpos]);
  786.    /*** update buffer position ***/
  787.    while( buffer[bufpos] is in {0-9eE+-} )
  788.      bufpos++;
  789. /* Note:  this routine does not take into account the situation like:
  790.    early data in file...... 10.23e49  ....... later data in file
  791.    buffer read n ---------------||----------- buffer read n+1 ...
  792. ScanString( char *s, int maxlen)
  793.    while (maxlen--)
  794.      if (bufpos == 1024)  LoadBuffer();
  795.      *s++ = buffer[bufpos++];
  796.      if (buffer[bufpos] is some character that does not belong in a string)
  797.        return;
  798. ParseFile()
  799.   while (!endoffile)
  800.     /* this will be a series of calls to ScanNumber() and ScanString()
  801.     ** that you'll have to figger out.
  802.     */
  803. - -- 
  804. - ------------------------------------------------------------------------------
  805. Brent P. Burton, N5VMG                          Department of Computer Science
  806. bpb9204@tamsun.tamu.edu                                   Texas A&M University
  807.       What are typical family values?      Good buys at WalMart.
  808. +++++++++++++++++++++++++++
  809. From: Michael Hecht <Michael_Hecht@mac.sas.com>
  810. Date: Wed, 30 Sep 1992 16:47:29 GMT
  811. Organization: SAS Institute Inc.
  812. In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au> ,
  813. u2005681@ucsvc.ucs.unimelb.edu.au writes:
  814. >As part of a new application, I am trying to read a text file of 
  815. >numbers and strings into a series of variables. The idea is to use the 
  816. >numbers as co-efficients for a simulation and the strings as labels for 
  817. >various graphs.
  818. I've written a routine that imports a tab-delimited text file in which
  819. the first record contains column names. You supply it with an FSSpec for
  820. the text file, a STR# id containing the column names you're looking for,
  821. and an action proc to be called for each row. It reads the data and for
  822. each row builds a string list of column values in the order you specified
  823. by the STR#. It then passes this info to the row action proc.
  824. I wrote it to use the Task Manager, so all the I/O could be async and
  825. reading/processing could take place in the background. This part could be
  826. easily removed, or replaced with Threads, however.
  827. If you're interested, let me know and I'll post it.
  828. - --Michael
  829. =======================================================================
  830. Michael P. Hecht                 | Internet:  Michael_Hecht@mac.sas.com
  831. SAS Institute Inc.; Cary, NC USA | AppleLink: SAS.HECHT
  832. +++++++++++++++++++++++++++
  833. From: beard@toadflax.UCDavis.EDU (Patrick C. Beard)
  834. Date: 30 Sep 92 19:40:29 GMT
  835. Organization: UC Davis, EECS Division of Computer Science
  836. In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au>,
  837. u2005681@ucsvc.ucs.unimelb.edu.au writes:
  838. > Hi folks,
  839. > I wonder if any of you people out there can give me some advice?
  840. > I've been programming for quite a while but I havn't had much to do
  841. > with the Mac file system and related toolbox calls.
  842. > As part of a new application, I am trying to read a text file of numbers
  843. > and strings into a series of variables. The idea is to use the numbers as
  844. > co-efficients for a simulation and the strings as labels for various graphs.
  845. > As I understand it, the Mac OS deals with text files as UNIX-C does with
  846. > binary files ie you specify how many bytes to read and what buffer to read
  847. > them into. But in the absence of a standard library, how is it possible to 
  848. > read numbers and strings of differing lengths?
  849. If you are programming in THINK C, use the ANSI library and save
  850. yourself a lot of work.
  851. With this library, you can open up files with fopen("filename", "r") and
  852. use fgets or fscanf
  853. to parse your input. Here's a fragment. Say your file has some numbers,
  854. all floats:
  855. 1.23 0.345 100.2
  856. [as many lines of this form as you like]
  857. A small program to read this would be:
  858. main()
  859.   float a, b, c; // numbers we'll be reading in.
  860.   FILE* f;       // stdio file pointer.
  861.   f = fopen("file", "r"); // open the file for reading.
  862.   while (fscanf(f, "%f %f %f", &a, &b, &c) != EOF) { // read the numbers.
  863.     printf("a = %f, b = %f, c = %f\n", a, b, c);
  864.   fclose(f);
  865. Reading strings is a matter of using %s rather than %f, unless of course
  866. your strings
  867. have embedded white space, which makes it more complicated. This should
  868. get you started.
  869. Good luck!
  870. // Patrick C. Beard
  871. // Department of Computer Science, U. C. Davis
  872. // pcbeard@ucdavis.edu
  873. +++++++++++++++++++++++++++
  874. From: Michael Hecht <Michael_Hecht@mac.sas.com>
  875. Date: Fri, 2 Oct 1992 13:46:55 GMT
  876. Organization: SAS Institute Inc.
  877. In article <1992Sep30.140336.3663@ucsvc.ucs.unimelb.edu.au> ,
  878. u2005681@ucsvc.ucs.unimelb.edu.au writes:
  879. >An explanation (or even some source code in C) would be most excellent.
  880. In article <BvEHB5.JL4@unx.sas.com> Michael Hecht,
  881. Michael_Hecht@mac.sas.com writes:
  882. >If you're interested, let me know and I'll post it.
  883. Well, I guess five requests warrants my sending this source code around
  884. the world. :-)
  885. Import uses Task Manager 2.3, which includes AtTaskExit/TaskExit support.
  886. If you don't have this version, you need to get it. Or, you could change
  887. the TASK #define to 0.
  888. Use it in good health!
  889. - --Michael
  890. =======================================================================
  891. Michael P. Hecht                 | Internet:  Michael_Hecht@mac.sas.com
  892. SAS Institute Inc.; Cary, NC USA | AppleLink: SAS.HECHT
  893. =======================================================================
  894. // /* Add these to the appropriate header file */
  895. // typedef struct {
  896. //    short            numStrings;
  897. //    Str255            string;
  898. // } **StringListHandle;
  899. // typedef OSErr ( *RowActionProc )( StringListHandle rowData,
  900. //                             long refCon );
  901. // OSErr Import( FSSpecPtr file, short columnListID,
  902. //                RowActionProc rowAction, long refCon );
  903.  *    Import() will read a tab-delimited text file given a file spec, 
  904.  *    a list of column names to look for (via a STR# id), and an action 
  905.  *    proc w/refCon to be executed for each row.
  906.  *    The column label string list should probably be purgeable.
  907.  *    This function is designed to be called from a task. If you don't 
  908.  *    want to call this from a task, change the TASK #define to 0.
  909.  *    Michael Hecht (Michael_Hecht@mac.sas.com)
  910.  *    1-oct-1992
  911. /* Change this to 0 if you're not using Task Manager 2.3 */
  912. #define TASK        1
  913. #if TASK
  914. #include "Task.h"
  915. #else
  916. #define TaskYield()
  917. #endif
  918. /* Size of our import buffer */
  919. #define kImportBufferSize        1024
  920. /* Context information needed for import */
  921. typedef struct {
  922.     HParmBlkPtr            pb;
  923.     long                bufIndex;
  924.     Boolean                endOfFile;
  925.     short                **columnMap;
  926.     short                nReqColumns;
  927.     StringListHandle    rowData;
  928. } ImportRecord, **ImportHandle;
  929. /* Import task exit routine. It cleans up all our storage, etc. */
  930. static void ImportExit( ImportHandle ctx )
  931.     if(( *ctx )->rowData )
  932.         DisposHandle(( Handle )( *ctx )->rowData );
  933.     if(( *ctx )->columnMap )
  934.         DisposHandle(( Handle )( *ctx )->columnMap );
  935.     if(( *ctx )->pb ) {
  936.         Ptr            buffer;
  937.         buffer = ( *ctx )->pb->ioParam.ioBuffer;
  938.         if( buffer )
  939.             DisposPtr( buffer );
  940.         if(( *ctx )->pb->ioParam.ioRefNum )
  941.             PBCloseSync(( ParmBlkPtr )(( *ctx )->pb ));
  942.         DisposPtr(( Ptr )( *ctx )->pb );
  943.     DisposHandle(( Handle )ctx );
  944. static OSErr TOpen( HParmBlkPtr pb )
  945.     OSErr                err;
  946.     pb->ioParam.ioCompletion = 0;
  947.     err = PBHOpenDFAsync( pb );
  948.     if( err != noErr )
  949.         return err;
  950.     while( pb->ioParam.ioResult > 0 )
  951.         TaskYield();
  952.     return pb->ioParam.ioResult;
  953. static OSErr TRead( HParmBlkPtr pb )
  954.     OSErr                err;
  955.     pb->ioParam.ioCompletion = 0;
  956.     err = PBReadAsync(( ParmBlkPtr )pb );
  957.     if( err != noErr )
  958.         return err;
  959.     while( pb->ioParam.ioResult > 0 )
  960.         TaskYield();
  961.     return pb->ioParam.ioResult;
  962. static OSErr SetIndString( ConstStr255Param s, StringListHandle strList,
  963. short i )
  964.     short                k;
  965.     Size                offset;
  966.     StringPtr            p;
  967.     if( i <= 0 )
  968.         return paramErr;
  969.     /* Add strings if necessary */
  970.     k = i - ( *strList )->numStrings;
  971.     if( k > 0 ) {
  972.         OSErr            err;
  973.         short            j;
  974.         /* Add enough length bytes to the end of the string list */
  975.         offset = GetHandleSize(( Handle )strList );
  976.         SetHandleSize(( Handle )strList, offset + k );
  977.         err = MemError();
  978.         if( err != noErr )
  979.             return err;
  980.         /* Initialize length bytes to 0 */
  981.         p = ( StringPtr )*strList + offset;
  982.         for( j = 0; j < k; j++ )
  983.             *p++ = 0;
  984.         ( *strList )->numStrings = i;
  985.     /* Determine the offset to the requested string */
  986.     offset = sizeof( short );
  987.     p = ( *strList )->string;
  988.     for( k = 1; k < i; k++ ) {
  989.         Size            length;
  990.         length = p[ 0 ] + 1;
  991.         offset += length;
  992.         p += length;
  993.     /* Replace the string */
  994.     Munger(( Handle )strList, offset, 0, p[ 0 ] + 1, ( Ptr )s, s[ 0 ] + 1 );
  995.     return MemError();
  996. static OSErr ReadField( ImportHandle ctx, StringPtr field, Boolean
  997. *endOfRecord )
  998.     OSErr                err;
  999.     Ptr                    buffer;
  1000.     short                length;
  1001.     char                c;
  1002.     buffer = ( *ctx )->pb->ioParam.ioBuffer + ( *ctx )->bufIndex;
  1003.     length = 0;
  1004.     *endOfRecord = FALSE;
  1005.     err = noErr;
  1006.     for( ;; ) {
  1007.         /* If the buffer is depleted, read some more in */
  1008.         if(( *ctx )->bufIndex >= ( *ctx )->pb->ioParam.ioActCount ) {
  1009.             /* If we've already reached the end of file, break out */
  1010.             if(( *ctx )->endOfFile ) {
  1011.                 err = eofErr;
  1012.                 *endOfRecord = TRUE;
  1013.                 break;
  1014.             /* Read the next buffer full */
  1015.             err = TRead(( *ctx )->pb );
  1016.             if( err != noErr ) {
  1017.                 /* Remember if we hit end of file, and keep going */
  1018.                 if( err == eofErr ) {
  1019.                     err = noErr;
  1020.                     ( *ctx )->endOfFile = TRUE;
  1021.                 }
  1022.                 /* Break out if any other read errors */
  1023.                 else
  1024.                     break;
  1025.             /* Reset index into buffer */
  1026.             ( *ctx )->bufIndex = 0;
  1027.             buffer = ( *ctx )->pb->ioParam.ioBuffer;
  1028.         /* Retrieve next character from buffer */
  1029.         c = *buffer++;
  1030.         ( *ctx )->bufIndex++;
  1031.         /* End of field? */
  1032.         if( c == '\t' )
  1033.             break;
  1034.         /* End of record? */
  1035.         if( c == '\r' ) {
  1036.             *endOfRecord = TRUE;
  1037.             break;
  1038.         /* Length exceeded? */
  1039.         if( length == sizeof( field ) - 1 )
  1040.             continue;
  1041.         /* Transfer to field */
  1042.         field[ ++length ] = c;
  1043.     /* Set string length */
  1044.     field[ 0 ] = length;
  1045.     return err;
  1046. static OSErr ReadHeader( ImportHandle ctx, short columnListID )
  1047.     OSErr                err;
  1048.     StringListHandle    columnList;
  1049.     short                i, nReqColumns, col;
  1050.     short                **columnMap;
  1051.     Str255                columnName, findName;
  1052.     Boolean                endOfRecord, found;
  1053.     /* Retrieve the string list */
  1054.     columnList = ( StringListHandle )GetResource( 'STR#', columnListID );
  1055.     if( !columnList ) {
  1056.         err = ResError();
  1057.         if( err == noErr )
  1058.             err = resNotFound;
  1059.         return err;
  1060.     /* Retrieve number of columns */
  1061.     nReqColumns = ( *columnList )->numStrings;
  1062.     ( *ctx )->nReqColumns = nReqColumns;
  1063.     /* Allocate column map */
  1064.     columnMap = ( short ** )NewHandle( 0 );
  1065.     if( !columnMap )
  1066.         return MemError();
  1067.     ( *ctx )->columnMap = columnMap;
  1068.     /* Read labels from first record */
  1069.     for( col = 1;; col++ ) {
  1070.         /* Let other tasks run */
  1071.         TaskYield();
  1072.         /* Read a field */
  1073.         err = ReadField( ctx, columnName, &endOfRecord );
  1074.         if( err != noErr )
  1075.             break;
  1076.         /* Map labels to column names */
  1077.         found = FALSE;
  1078.         for( i = 1; i <= nReqColumns; i++ ) {
  1079.             GetIndString( findName, columnListID, i );
  1080.             if( EqualString( columnName, findName, FALSE, FALSE )) {
  1081.                 found = TRUE;
  1082.                 break;
  1083.         /* If not found, then this column will be ignored */
  1084.         if( !found )
  1085.             i = 0;
  1086.         /* Append to column map */
  1087.         err = PtrAndHand(( Ptr )&i, ( Handle )columnMap, sizeof( i ));
  1088.         if( err != noErr )
  1089.             break;
  1090.         if( endOfRecord )
  1091.             break;
  1092.     if( err == eofErr )
  1093.         err = noErr;
  1094.     return err;
  1095. static OSErr ReadData( ImportHandle ctx, RowActionProc rowAction, long
  1096. refCon )
  1097.     OSErr                err;
  1098.     short                col, nReqColumns, nColumns;
  1099.     StringPtr            p;
  1100.     short                **columnMap, i;
  1101.     StringListHandle    rowData;
  1102.     Boolean                endOfRecord;
  1103.     Str255                field;
  1104.     columnMap = ( *ctx )->columnMap;
  1105.     nColumns = GetHandleSize(( Handle )columnMap )/sizeof( short );
  1106.     /* Allocate rowData string list */
  1107.     nReqColumns = ( *ctx )->nReqColumns;
  1108.     rowData = ( StringListHandle )NewHandle( sizeof( short ) + nReqColumns );
  1109.     if( !rowData )
  1110.         return MemError();
  1111.     ( *ctx )->rowData = rowData;
  1112.     /* Read rows until an error occurs */
  1113.     for( ;; ) {
  1114.         /* Initialize row data to nReqColumns empty strings */
  1115.         ( *rowData )->numStrings = nReqColumns;
  1116.         p = ( *rowData )->string;
  1117.         for( i = 0; i < nReqColumns; i++ ) {
  1118.             *p++ = 0;
  1119.         /* Read a row */
  1120.         for( col = 0, endOfRecord = FALSE; !endOfRecord; col++ ) {
  1121.             /* Let other tasks run */
  1122.             TaskYield();
  1123.             /* Read a field */
  1124.             err = ReadField( ctx, field, &endOfRecord );
  1125.             if( err != noErr )
  1126.                 break;
  1127.             /* Skip excess unlabeled columns */
  1128.             if( col >= nColumns )
  1129.                 continue;
  1130.             /* Get column index; skip unrecognized columns */
  1131.             i = ( *columnMap )[ col ];
  1132.             if( i == 0 )
  1133.                 continue;
  1134.             /* Insert this field into the row data */
  1135.             err = SetIndString( field, rowData, i );
  1136.             if( err != noErr )
  1137.                 break;
  1138.         /* Get out now if errors occurred */
  1139.         if( err != noErr )
  1140.             break;
  1141.         /* Call row action proc */
  1142.         err = ( *rowAction )( rowData, refCon );
  1143.         if( err != noErr )
  1144.             break;
  1145.         /* Reset row data for next row */
  1146.         SetHandleSize(( Handle )rowData, sizeof( short ) + nReqColumns );
  1147.     if( err == eofErr )
  1148.         err = noErr;
  1149.     return err;
  1150. OSErr Import( FSSpecPtr file, short columnListID,
  1151.                 RowActionProc rowAction, long refCon )
  1152.     OSErr                err;
  1153.     ImportHandle        ctx;
  1154.     short                exitLevel;
  1155.     HParmBlkPtr            pb;
  1156.     Ptr                    buffer;
  1157.     /* Allocate import context info */
  1158.     ctx = ( ImportHandle )NewHandle( sizeof( ImportRecord ));
  1159.     if( !ctx )
  1160.         return MemError();
  1161. #if TASK
  1162.     /* Install exit routine */
  1163.     err = AtTaskExit(( TaskProcPtr )ImportExit, ( long )ctx, &exitLevel );
  1164.     if( err != noErr ) {
  1165.         DisposHandle(( Handle )ctx );
  1166.         return err;
  1167. #endif
  1168.     /* Initialize context info */
  1169.     ( *ctx )->pb = 0;
  1170.     ( *ctx )->bufIndex = 0;
  1171.     ( *ctx )->endOfFile = FALSE;
  1172.     ( *ctx )->columnMap = 0;
  1173.     ( *ctx )->rowData = 0;
  1174.     /* Allocate the parameter block */
  1175.     pb = ( HParmBlkPtr )NewPtr( sizeof( HParamBlockRec ));
  1176.     if( !pb ) {
  1177.         err = MemError();
  1178.         goto errExit;
  1179.     ( *ctx )->pb = pb;
  1180.     /* Fill out parameter block for open */
  1181.     pb->ioParam.ioRefNum = 0;
  1182.     pb->ioParam.ioBuffer = 0;
  1183.     pb->ioParam.ioVRefNum = file->vRefNum;
  1184.     pb->fileParam.ioDirID = file->parID;
  1185.     pb->ioParam.ioNamePtr = file->name;
  1186.     pb->ioParam.ioVersNum = 0;
  1187.     pb->ioParam.ioPermssn = fsRdPerm;
  1188.     pb->ioParam.ioMisc = 0;
  1189.     /* Open the import file */
  1190.     err = TOpen( pb );
  1191.     if( err != noErr )
  1192.         goto errExit;
  1193.     /* Allocate the input buffer */
  1194.     buffer = NewPtr( kImportBufferSize );
  1195.     if( !buffer ) {
  1196.         err = MemError();
  1197.         goto errExit;
  1198.     /* Set up parameter block for reading */
  1199.     pb->ioParam.ioBuffer = buffer;
  1200.     pb->ioParam.ioReqCount = kImportBufferSize;
  1201.     pb->ioParam.ioActCount = 0;
  1202.     pb->ioParam.ioPosMode = fsAtMark;
  1203.     pb->ioParam.ioPosOffset = 0;
  1204.     /* Read the header */
  1205.     err = ReadHeader( ctx, columnListID );
  1206.     if( err != noErr )
  1207.         goto errExit;
  1208.     /* Read the data */
  1209.     err = ReadData( ctx, rowAction, refCon );
  1210. errExit:
  1211. #if TASK
  1212.     TaskExit( exitLevel );
  1213. #else
  1214.     ImportExit( ctx );
  1215. #endif
  1216.     return err;
  1217. =======================================================================
  1218. /* This example shows how you would create a task that calls Import */
  1219. #include "Task.h"
  1220. #define kColumnLabels    131
  1221. static OSErr ImportRow( StringListHandle rowData, long refCon )
  1222.     /* Process the row data here */
  1223.     /* Return an error code (ie: userCanceledErr) to stop */
  1224.     return noErr;
  1225. static void ImportTask( FSSpecPtr file )
  1226.     UnexpectedError( Import( file, kColumnLabels, ImportRow, 0 ));
  1227. OSErr NewImportTask( FSSpecPtr file )
  1228.     /* Spawn a task to import the text file */
  1229.     return NewTask(( TaskProcPtr )ImportTask, ( long )file, 0 );
  1230. ---------------------------
  1231. End of C.S.M.P. Digest
  1232. **********************
  1233.